﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using MicroTest_Client;
using MicroTest.Properties;
using NAnoto;
using System.Drawing.Imaging;

namespace MicroTest
{
    public partial class FrmClass : Form
    {
        /// <summary>
        /// 此变量无用
        /// </summary>
        private FrmDetails frmDetails;
        /// <summary>
        /// 主界面是的书写小窗口集合，以点阵笔序列号为键值
        /// </summary>
        private Dictionary<string, DrawingWindow> statusWindows;
        /// <summary>
        /// 笔列表字典集合
        /// </summary>
        private Dictionary<string, PenItem> penItemList;
        /// <summary>
        /// 点阵笔总数，已连接的点阵笔数，断开连接的点阵笔数
        /// </summary>
        private int All=0, Conn=0, Disconn=0;
        /// <summary>
        /// 等待导出总学生人数
        /// </summary>
        public int StudentToExportCount = 0;
        /// <summary>
        /// 已经导出的学生人数
        /// </summary>
        public int StudentExportedCount = 0;
        /// <summary>
        /// 是否加载了SYM文件
        /// </summary>
        private bool IsSymLoaded = false;
        /// <summary>
        /// backgroundworker
        /// </summary>
        private BackgroundWorker backgroundWorker;
        /// <summary>
        /// 是否正在导出数据 
        /// </summary>
        public bool IsExporting = false;
        /// <summary>
        /// 是否在导入课件
        /// </summary>
        public bool IsLoadingSym = false;
        /// <summary>
        /// 导出数据是否成功
        /// </summary>
        private bool ExportSuccess = false;

        private string UploadMsg = string.Empty;
        /// <summary>
        /// 落笔状态
        /// </summary>
        private Dictionary<string, bool> PenDownStatus;
        /// <summary>
        /// 笔序列号与学生姓名的对应的字典
        /// </summary>
        private Dictionary<string, string> studentListDic;
        /// <summary>
        /// 异步数据存储类
        /// </summary>
        private SaveStrokeAsync saveStrokeAsync;
        //private FrmZoom frmZoom;
        //private Image BackgroundImage = null;
        /// <summary>
        /// sym文件信息
        /// </summary>
        private SYMInfo SymInfo = null;
        /// <summary>
        /// 当前点击的左侧学生列表项
        /// </summary>
        private PenItem currentPenItem = null;
        /// <summary>
        /// 窗口宽
        /// </summary>
        private int windowWidth = 0;
        /// <summary>
        /// 窗口高
        /// </summary>
        private int windowHeight = 0;
        /// <summary>
        /// 缩放尺寸
        /// </summary>
        private List<ZoomSize> zoomValues = new List<ZoomSize>();
        /// <summary>
        /// 绘制窗口最小宽度
        /// </summary>
        private const int minDrawingWidth = 210;
        /// <summary>
        /// 绘制窗口最小高度
        /// </summary>
        private const int minDrawingHeight = 297;
        /// <summary>
        /// 绘制窗口底部信息状态条高度
        /// </summary>
        private const int drawingWindowNameHeight = 35;
        /// <summary>
        /// 是否显示背景
        /// </summary>
        private bool ShowBackground = true;
        /// <summary>
        /// 是否是数据恢复模式
        /// </summary>
        public bool ResumeMode = false;
        /// <summary>
        /// 笔替换结果提示窗口
        /// </summary>
        FrmPromot frm = new FrmPromot();

        public FrmClass()
        {
            InitializeComponent();
            frmDetails = new FrmDetails();
           

            statusWindows = new Dictionary<string, DrawingWindow>();
            penItemList = new Dictionary<string, PenItem>();
            //listView1.Columns.Add("点阵笔列表", listView1.Width);
            backgroundWorker = new BackgroundWorker();
            backgroundWorker.DoWork += BackgroundWorker_DoWork;

            this.WindowState = FormWindowState.Maximized;
            studentListDic = new Dictionary<string, string>();
            PenDownStatus = new Dictionary<string, bool>();
            //InitControl();

        }
        /// <summary>
        /// 考试初始化操作
        /// </summary>
        public void IniClass()
        {
            InitControl();
            ShowBackground = true;
            btnBackground.NormalImage = Resources.oper_btn_hidebg;
            btnBackground.HoverImage = Resources.oper_btn_hidebg_hover;
            btnBackground.DownImage = Resources.oper_btn_hidebg_active;
            btnBackground.DisableImage = Resources.oper_btn_hidebg_disabled;
            //examStatus = ExamStatus.Exam_Sign;
            IsSymLoaded = false;
            IsExporting = false;
            ExportSuccess = false;

            //回复异常
            //ResumeMode = ResumeData();
            //学生名单
            //Program.MTInfo.ClearStudentCard();

            Program.CurrentClassInfo.ClearStudentCard();
            List<StudentCard> cardList = Program.StudentInfo.GetCardList();
            foreach (var item in cardList)
            {
                //Program.MTInfo.AddStudentCard(item);
                Program.CurrentClassInfo.AddStudentCard(item);
            }
            //清空小窗
            statusWindows.Clear();
            flpClient.Controls.Clear();

            Conn = 0;
            All = Program.StudentInfo.BandList.Count;
            Disconn = All;
            UpdateCountStatus();
            penItemList.Clear();
            flpPenlist.Controls.Clear();

            studentListDic.Clear();
            AddPenList();


            if(ResumeMode)
            {
                //labKS.Text ="【"+ Program.MTInfo.MicroTestTitle+"】";
                ELogger.Trace("上课数据恢复模式");
                labKS.Text= "【" + Program.CurrentClassInfo.ClassSymTitle + "】";
                labKS.Top = labBJ.Top;
                labKS.Left = labBJ.Right;
                LoadDrawingWindws();
                IsSymLoaded = true;
            }
            else
            {
                labKS.Text = "";
            }
            if(Program.CurrentClassInfo.Login==false)
            {
                btnGoToExam.Visible = false;
            }

            
        }
        /// <summary>
        /// 把签到名单中的笔添加到笔列表
        /// </summary>
        private void AddPenList()
        {
            foreach (var item in Program.StudentInfo.BandList)
            {
                PenItem pi = new PenItem();
                pi.PenSerial = item.PenSerial;
                pi.NormalImage = Resources.pen_ico_link;
                pi.DisableImage = Resources.pen_ico_fail;
                pi.DisconectedImage = Resources.pen_ico_fail;
                pi.SetName(item.Name);
                pi.SelectedColor = Color.FromArgb(226, 175, 134);
                pi.ChangePenStatus(PenStatus.Disabled);
                pi.ClickPen += Pi_ClickPen;
                studentListDic.Add(item.PenSerial, item.Name);
                penItemList.Add(item.PenSerial, pi);
                flpPenlist.Controls.Add(pi);
            }
        }
        /// <summary>
        /// 用旧笔替换新笔
        /// </summary>
        /// <param name="penserial"></param>
        private string ReplacePenItem(string penserial)
        {
            
            PenItem pi = null;
            string oldPenSerial = string.Empty;
            string studentName = studentListDic[penserial];
            foreach (var item in studentListDic)
            {
                if(studentName.Equals(item.Value)&&!penserial.Equals(item.Key))
                {
                    oldPenSerial = item.Key;
                    break;

                }
            }
            foreach (var item in penItemList)
            {
                if(oldPenSerial.Equals(item.Value.PenSerial))
                {
                    pi = item.Value;
                    //oldPenSerial = item.Key;
                    break;
                }
            }
            if(pi!=null)
            {
                //pi.PenSerial = penserial;
                this.Invoke(new Action(() => { pi.PenSerial = penserial;pi.SetName(studentName); }));
                if(penItemList.ContainsKey(oldPenSerial))
                    penItemList.Remove(oldPenSerial);
                if (penItemList.ContainsKey(penserial) == false)
                    penItemList.Add(penserial, pi);
            }
            return oldPenSerial;
        }

        /// <summary>
        /// 更新笔的签到状态
        /// </summary>
        /// <param name="penSerial"></param>
        /// <param name="ps"></param>
        private void UpdatePenSignInStatus(string penSerial,PenStatus ps)
        {
            if(this.InvokeRequired)
            {
                Action<string, PenStatus> ac = new Action<string, PenStatus>(UpdatePenSignInStatus);
                this.Invoke(ac, new object[] { penSerial, ps });
            }
            else
            {
                if (penItemList[penSerial].PenItemStatus != ps)
                {
                    penItemList[penSerial].ChangePenStatus(ps);
                    if(ps==PenStatus.Normal)
                    {
                        Conn++;
                        Disconn--;
                    }
                    else if(ps==PenStatus.DisConnected)
                    {
                        Conn--;
                        Disconn++;
                    }
                    UpdateCountStatus();
                }
            }
            
        }
        /// <summary>
        /// 载入所有人的书写小窗口
        /// </summary>
        private void LoadDrawingWindws()
        {
            bool isA4Page = true;
            foreach (var stu in studentListDic)
            {
                string penSerial = stu.Key;
                //DrawingWindow cs = new DrawingWindow(penSerial, Program.MTInfo.MicroTestPaperImage,ResumeMode);
                DrawingWindow cs = new DrawingWindow(penSerial, Program.CurrentClassInfo.ClassSymImage, ResumeMode);

                cs.SetName(stu.Value);
                statusWindows.Add(penSerial, cs);
                int width = flpClient.Width;
                if (windowHeight != 0)
                {
                    cs.Height = windowHeight;
                    cs.Width = windowWidth;
                }
                else
                {
                    //if (Program.MTInfo.MicroTestPaperImage.Count != 0)
                    if (Program.CurrentClassInfo.ClassSymImage.Count != 0)
                    {
                        //foreach (var item in Program.MTInfo.MicroTestPaperImage)
                        foreach (var item in Program.CurrentClassInfo.ClassSymImage)
                        {
                            if (item.Value.Width < item.Value.Height)
                            {
                                windowWidth = minDrawingWidth;
                                windowHeight = minDrawingHeight + drawingWindowNameHeight;
                            }
                            else
                            {
                                isA4Page = false;
                                windowWidth = 2* minDrawingWidth;
                                windowHeight = minDrawingHeight + drawingWindowNameHeight;
                            }
                            break;
                        }
                        cs.Width = windowWidth;
                        cs.Height = windowHeight;

                    }
                }
                int w = cs.Width;
                int l = width % w / 2;
                cs.Margin = new Padding(20, 10, 20, 10);
                flpClient.Controls.Add(cs);
                foreach (var item in flpClient.Controls)
                {
                    (item as DrawingWindow).SetLabelVisable(true);
                    //(item as DrawingWindow).Visible = true;

                }
            }
            zoomValues.Clear();
            int smallWidth = minDrawingWidth;
            int smallHeight = minDrawingHeight;
            if (!isA4Page)
                smallWidth = 2 * minDrawingWidth;
            
            ZoomSize sz = new ZoomSize(smallWidth, smallHeight + drawingWindowNameHeight);
            zoomValues.Add(sz);

            int clientAreaHeight = flpClient.Height-10;
            int clientAreaWidth = flpClient.Width-20-20;

            int drawingWindowHeight = clientAreaHeight;
            int drawingWindowWidth = (int)(1.0 * (drawingWindowHeight - drawingWindowNameHeight) * smallWidth / smallHeight);
            sz = new ZoomSize(drawingWindowWidth, drawingWindowHeight);
            zoomValues.Add(sz);


            drawingWindowWidth = clientAreaWidth;
            drawingWindowHeight = (int)(1.0 * drawingWindowWidth / smallWidth * smallHeight) + drawingWindowNameHeight;
            sz = new ZoomSize(drawingWindowWidth, drawingWindowHeight);
            zoomValues.Add(sz);




        }
        /// <summary>
        /// 用新笔替换原有的笔
        /// </summary>
        /// <param name="penserial"></param>
        private string ReplaceDrawingWindow(string penserial)
        {
            DrawingWindow dw = null;
            string oldPenSerial = string.Empty;
            string studentName = studentListDic[penserial];
            foreach (var item in studentListDic)
            {
                if (studentName.Equals(item.Value) && !penserial.Equals(item.Key))
                {
                    oldPenSerial = item.Key;
                    break;
                }
            }
            foreach (var item in statusWindows)
            {
                if (oldPenSerial.Equals(item.Value.GetPenSerial()))
                {
                    dw = item.Value;
                    //oldPenSerial = item.Key;
                    break;
                }
            }
            if (dw != null)
            {
                this.Invoke(new Action(() => { dw.ReplacePenSerial(penserial); }));

                //dw.ReplacePenSerial( penserial);
                if (statusWindows.ContainsKey(oldPenSerial))
                    statusWindows.Remove(oldPenSerial);
                if (statusWindows.ContainsKey(penserial) == false)
                    statusWindows.Add(penserial, dw);
            }
            return oldPenSerial;
        }
        /// <summary>
        /// 显示笔替换结果
        /// </summary>
        /// <param name="studentName"></param>
        /// <param name="oldPenserial"></param>
        /// <param name="newPenserial"></param>
        private void ShowReplaceResult(string studentName,string oldPenserial,string newPenserial)
        {
            if(this.InvokeRequired)
            {
                Action<string, string, string> ac = new Action<string, string, string>(ShowReplaceResult);
                this.Invoke(ac, new object[] { studentName, oldPenserial, newPenserial });
            }
            else
            {
                frm.Show();
                frm.SetPromptString(string.Format("【{0}】的点阵笔已替换为【{1}】", studentName, newPenserial));
                ELogger.Trace(string.Format("【{0}】的点阵笔已替换为【{1}】", studentName, newPenserial));
            }
        }
        
        /// <summary>
        /// 后台线程
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {

            BackgroundWorkPara para = e.Argument as BackgroundWorkPara;
            switch (para.OperationMode)
            {
                case OperationMode.UploadMt:
                    break;
                case OperationMode.LoadSym:
                    {
                        SYMTOAFD sym2afd = new SYMTOAFD();
                        SymInfo = sym2afd.UNZIPSYM(openFileDialog.FileName);
                        Program.CurrentClassInfo.ClearSymPageImage();
                        foreach (var item in SymInfo.lstSYMPNG)
                        {
                            Image img = Image.FromFile(item.Value.PngFile);
                            Bitmap bitmap = new Bitmap(img, new Size(img.Width / 2, img.Height / 2));
                            img.Dispose();
                            Program.CurrentClassInfo.AddSymPageImage(item.Value.PageAddress, bitmap);
                        }
                        IsLoadingSym = false;
                    }
                    break;
                case OperationMode.ExportWriting:
                    {
                        //string className = labKS.Text.Substring(labKS.Text.IndexOf('【'));
                        //className = className.Substring(0, className.Length - className.IndexOf('】'));
                        string className = Program.CurrentClassInfo.ClassSymTitle;
                        string folder = para.Path + "\\" + className +"_"+ DateTime.Now.ToString("yyyyMMddHHmmss");
                        if (Directory.Exists(folder) == false)
                            Directory.CreateDirectory(folder);
                        foreach (var item in statusWindows)
                        {
                            string key = item.Key;
                            DrawingWindow dw = item.Value;
                            dw.SaveDrawingImage();
                            string studentName = dw.GetWindowPenName();
                            string folderStudent = folder + "\\" + studentName;
                            Directory.CreateDirectory(folderStudent);
                            string pdfFile = folderStudent + "\\" + studentName + "_" + key + ".pdf";
                            
                            Dictionary<string, string> drawings = dw.GetDrawingImagesPath();

                            iTextSharp.text.Document doc = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4,1,1,1,1);
                            iTextSharp.text.pdf.PdfWriter.GetInstance(doc, new FileStream(pdfFile, FileMode.CreateNew));
                            doc.Open();
                            //doc.SetMargins(0.1f, 0.1f, 0.1f, 0.1f);
                            int pageCount = Program.CurrentClassInfo.ClassSymImage.Count;
                            int index = 0;
                            foreach (var bg in Program.CurrentClassInfo.ClassSymImage)
                            {
                                string pageSerial = bg.Key;
                                Bitmap bit = new Bitmap(bg.Value);
                                Graphics gra = Graphics.FromImage(bit);
                                Image drawing = Image.FromFile(drawings[pageSerial]);
                                gra.DrawImage(drawing, new Rectangle(0, 0, bit.Width, bit.Height), new Rectangle(0, 0, drawing.Width, drawing.Height), GraphicsUnit.Pixel);
                                
                                //string imgPaht=folderStudent + "\\" + studentName + "_" + key +"_ "+index.ToString()+".jpg";
                                //bit.Save(imgPaht);
                                iTextSharp.text.Image itextImage = iTextSharp.text.Image.GetInstance(bit,ImageFormat.Png);
                                int picWidth = bit.Width;
                                int percent = (int)(1.0 * 596 / picWidth * 100);
                                itextImage.ScalePercent(percent);
                                
                                bit.Dispose();
                                doc.Add(itextImage);
                                drawing.Dispose();

                                index++;
                                if (pageCount > index)
                                    doc.NewPage();
                            }

                            doc.Close();
                            StudentExportedCount++;
                        }
                        ExportSuccess = true;
                        IsExporting = false;

                    }
                    break;
                default:
                    break;
            }
            
        }

       
        /// <summary>
        /// 退出课堂
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnExit_Click(object sender, EventArgs e)
        {
            if(DialogResult.OK==MessageBox.Show("是否退出？", "维思课堂", MessageBoxButtons.OKCancel,MessageBoxIcon.Question))
            {
                ELogger.Trace("退出上课");
               
                this.Close();
                Application.Exit();
            }
            //focusBtn.Focus();
        }
        /// <summary>
        /// 更新连接状态提示信息
        /// </summary>
        private void UpdateCountStatus()
        {
            if(this.InvokeRequired)
            {
                Action ac = new Action(UpdateCountStatus);
                this.Invoke(ac);
            }
            else
            {
                this.labTotal.Text ="总人数："+ All.ToString();
                this.labCon.Text = "已连接："+Conn.ToString();
                this.labDis.Text = "未连接："+Disconn.ToString();
                ELogger.Trace(string.Format("总人数：{0}，已连接：{1}，未连接：{2}", All, Conn, Disconn));
            }
        }
        /// <summary>
        /// 更新笔连接列表的连接状态
        /// </summary>
        /// <param name="penSerial"></param>
        /// <param name="conn"></param>
        private void UpdatePenListStatus(string penSerial,bool conn=true)
        {
            if (this.InvokeRequired)
            {

                Action<string,bool> ac = new Action<string,bool>(UpdatePenListStatus);
                this.Invoke(ac, new object[] { penSerial, conn });
            }
            else
            {
                foreach (var item in flpPenlist.Controls)
                {
                    PenItem pi = (PenItem)item;
                    if(pi.PenSerial.Equals(penSerial))
                    {
                        if (conn)
                            pi.ChangePenStatus(PenStatus.Normal);
                        else
                            pi.ChangePenStatus(PenStatus.DisConnected);
                        break;
                    }
                }

            }
        }
        /// <summary>
        /// 将标签与学生信息关联
        /// </summary>
        /// <param name="penserial"></param>
        /// <param name="pageSerial"></param>
        /// <param name="nx"></param>
        /// <param name="ny"></param>
        private void MapPenserialToStudent(string penserial,string pageSerial,int nx,int ny)
        {
            if(!studentListDic.ContainsKey(penserial))
            {
                //string name=Program.MTInfo.GetStudentName(pageSerial, nx, ny);
                string name =Program.CurrentClassInfo.GetStudentName(pageSerial, nx, ny);
                if (!string.IsNullOrEmpty(name))
                    studentListDic[penserial] = name;
            }
        }
        
        /// <summary>
        /// 点击左侧列表
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void Pi_ClickPen(object sender, ClickPenEventArgs args)
        {
            if (flpClient.Controls.Count == 0)
                return;
            if (currentPenItem != null)
                currentPenItem.Selected = false;
            currentPenItem = (sender as PenItem);
            currentPenItem.Selected = true;
            if (flpClient.Controls.Count == penItemList.Count)
            {
                foreach (var item in statusWindows)
                {
                    if (args.ItemName.Equals(item.Value.GetPenSerial()))
                    {
                        if (flpClient.VerticalScroll.Visible == false)
                            return;
                        int top = item.Value.Top;
                        int hpos = flpClient.HorizontalScroll.Value;
                        int pos = flpClient.VerticalScroll.Value + top;
                        flpClient.VerticalScroll.Value = pos;
                        flpClient.VerticalScroll.Value = pos;
                    }
                }
            }
            else
            {
                if (statusWindows.ContainsKey(args.ItemName)
                    && !args.ItemName.Equals((flpClient.Controls[0] as DrawingWindow).GetPenSerial()))
                {
                    flpClient.SuspendLayout();

                    flpClient.Controls.Add(statusWindows[args.ItemName]);
                    flpClient.Controls.RemoveAt(0);
                    flpClient.ResumeLayout();

                }

            }
            
        }

        //private void UpdateStatusWindowName(string penSerial,string studentName)
        //{
        //    if(this.InvokeRequired)
        //    {
        //        Action<string, string> ac = new Action<string, string>(UpdateStatusWindowName);
        //        this.Invoke(ac, new object[] { penSerial, studentName });
        //    }
        //    else
        //    {
        //        statusWindows[penSerial].SetName(studentListDic[penSerial]);

        //    }
        //}
        //private void UpdatePenListItemName(PenItem pi,string penName)
        //{
        //    if (this.InvokeRequired)
        //    {
        //        Action<PenItem, string> ac = new Action<PenItem, string>(UpdatePenListItemName);
        //        this.Invoke(ac, new object[] { pi, penName });
        //    }
        //    else
        //    {
        //        pi.SetName(studentListDic[penName]);

        //    }
        //}
        /// <summary>
        /// 抬笔
        /// </summary>
        /// <param name="time"></param>
        /// <param name="penSerial"></param>
        /// <param name="penType"></param>
        public void DigitalPen_PenUp(ulong time, string penSerial, int penType)
        {
            if (true== IsExporting)
                return;
            if (penItemList.ContainsKey(penSerial))
            {
                UpdatePenSignInStatus(penSerial, PenStatus.Normal);
            }
            else if(studentListDic.ContainsKey(penSerial))
            {
                string oldPenSerial=ReplacePenItem(penSerial);
                ReplaceDrawingWindow(penSerial);
                if (studentListDic.ContainsKey(oldPenSerial))
                    studentListDic.Remove(oldPenSerial);
                Program.StudentInfo.UpdateCardPenSerial(oldPenSerial, penSerial);

                string folder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\WiseClass";
                if (!Directory.Exists(folder))
                    Directory.CreateDirectory(folder);
                folder = folder + "\\BindInfo";
                if (!Directory.Exists(folder))
                    Directory.CreateDirectory(folder);
                string bindData = string.Format("{0}\\{1}.cla", folder, Program.CurrentClassInfo.ClassRoomInfo);

                //string folder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\WiseClass";

                //if (!Directory.Exists(folder))
                //    Directory.CreateDirectory(folder);
                //string bindData = folder + "\\StudentList.cla";
                if (File.Exists(bindData))
                    File.Delete(bindData);
                bool ret = SerializeHelper.SerialData(bindData, Program.StudentInfo);
                if (ret)
                    ELogger.Trace("存储新名单成功");
                else
                    ELogger.Trace("存储新名单失败");
                ShowReplaceResult(studentListDic[penSerial], oldPenSerial, penSerial);
            }
            if (true==IsSymLoaded)
            {
                UpdatePenStatus(penSerial, 3);
            }
            
        }
        /// <summary>
        /// 落笔事件
        /// </summary>
        /// <param name="time"></param>
        /// <param name="penSerial"></param>
        /// <param name="penType"></param>
        public void DigitalPen_PenDown(ulong time, string penSerial, int penType)
        {
            if (true == IsExporting)
                return;
            if (studentListDic.ContainsKey(penSerial))
            {
                UpdatePenSignInStatus(penSerial, PenStatus.Normal);
            }
            //IsPenDown = true;
            if (PenDownStatus.ContainsKey(penSerial))
                PenDownStatus[penSerial] = true;
            else
                PenDownStatus.Add(penSerial, true);
            UpdatePenStatus(penSerial, 2);
            //if(examStatus==ExamStatus.Exam_Examing)
            //    saveStrokeAsync.PutPenDownEvent(penSerial);

        }
        /// <summary>
        /// 坐标事件
        /// </summary>
        /// <param name="time"></param>
        /// <param name="penSerial"></param>
        /// <param name="penType"></param>
        /// <param name="pageSerial"></param>
        /// <param name="pageId"></param>
        /// <param name="cx"></param>
        /// <param name="cy"></param>
        /// <param name="force"></param>
        public void DigitalPen_PenCoordinate(ulong time, string penSerial, int penType, string pageSerial, ulong pageId, int cx, int cy, byte force)
        {
            if (true == IsExporting)
                return;

            bool IsPaperPageSerial = Program.CurrentClassInfo.IsPaperPageSerial(pageSerial);
            bool IsStudentCard = Program.CurrentClassInfo.IsStudentCardPage(pageSerial);
            if (!IsPaperPageSerial/*Program.CurrentClassInfo.IsPaperPageSerial(pageSerial)*/ && !IsStudentCard/*Program.CurrentClassInfo.IsStudentCardPage(pageSerial)*/)
            {
                ELogger.Error(string.Format("{0} 非考试用纸，非学生标签！", pageSerial));
                return;
            }
            if (PenDownStatus.ContainsKey(penSerial) && PenDownStatus[penSerial])
            {
                PenDownStatus[penSerial] = false;
                //改学生名字
                MapPenserialToStudent(penSerial, pageSerial, cx, cy);

            }
            if (true == IsSymLoaded&& IsPaperPageSerial/*Program.MTInfo.IsPaperPageSerial(pageSerial)*/)
            {
                UpdateStroke(penSerial, pageSerial, cx, cy);
            }   
        }
        /// <summary>
        /// 点阵笔连接
        /// </summary>
        /// <param name="time"></param>
        /// <param name="penSerial"></param>
        /// <param name="penType"></param>
        public void DigitalPen_PenConnected(ulong time, string penSerial, int penType)
        {
            if (true == IsExporting)
                return;
            ELogger.Trace(string.Format("{0} 建立连接", penSerial));

            if (studentListDic.ContainsKey(penSerial))
            {
                UpdatePenSignInStatus(penSerial, PenStatus.Normal);
            }
            
            //Conn++;
            //Disconn = All - Conn;
            //UpdatePenStatus(penSerial, 0);
            //UpdateCountStatus();
            //UpdatePenListStatus(penSerial);
        }
        /// <summary>
        /// 笔断开
        /// </summary>
        /// <param name="time"></param>
        /// <param name="penSerial"></param>
        /// <param name="penType"></param>
        public void DigitalPen_PenDisconnect(ulong time, string penSerial, int penType)
        {
            if (true == IsExporting)
                return;
            ELogger.Trace(string.Format("{0} 断开连接", penSerial));
            if (studentListDic.ContainsKey(penSerial))
            {
                UpdatePenSignInStatus(penSerial, PenStatus.DisConnected);
            }
            //if (!IsTesting)
            //    return;
            //if (statusWindows.ContainsKey(penSerial) == false)
            //{
            //    AddCS2MainWindow(penSerial);
               
            //}
            //Conn--;
            //Disconn = All - Conn;
            //statusWindows[penSerial].PenDisconnectedEvent(penSerial);
            //UpdatePenStatus(penSerial, 1);

           // UpdateCountStatus();
            //UpdatePenListStatus(penSerial,false);
        }
        /// <summary>
        /// 更新笔迹显示窗口笔的书写状态提示
        /// </summary>
        /// <param name="penserial"></param>
        /// <param name="statusType"></param>
        private void UpdatePenStatus(string penserial,int statusType)
        {
            if (this.InvokeRequired)
            {
                Action<string, int> ac = new Action<string, int>(UpdatePenStatus);
                this.Invoke(ac, new object[] { penserial, statusType });

            }
            else
            {
                if (statusWindows.ContainsKey(penserial) == false)
                    return;
                switch (statusType)
                {
                    case 0://con
                        statusWindows[penserial].PenConnectedEvent(penserial);

                        break;
                    case 1://dis
                        statusWindows[penserial].PenDisconnectedEvent(penserial);

                        break;
                    case 2://down
                        statusWindows[penserial].OnPenDown(penserial);
                        break;
                    case 3://up
                        statusWindows[penserial].OnPenUp(penserial);

                        break;
                    default:
                        break;
                }
            }
        }
        /// <summary>
        /// 发送笔迹坐标到小窗口
        /// </summary>
        /// <param name="penserial"></param>
        /// <param name="pageSerial"></param>
        /// <param name="cx"></param>
        /// <param name="cy"></param>
        private void UpdateStroke(string penserial, string pageSerial,int cx,int cy)
        {
            if (this.InvokeRequired)
            {
                Action<string, string,int,int> ac = new Action<string, string, int, int>(UpdateStroke);
                this.Invoke(ac, new object[] { penserial, pageSerial, cx, cy });

            }
            else
            {
                if(statusWindows.ContainsKey(penserial))
                    statusWindows[penserial].PenCoordinates(penserial, pageSerial, cx, cy);
            }
        }
        
        /// <summary>
        /// 初始化
        /// </summary>
        private void InitControl()
        {
            this.tlpBase.Visible = false;
            {
                
                //列表
                flpPenlist.Width = flpPenlist.Parent.Width;
                flpPenlist.Height = flpPenlist.Parent.Height - 34 - 2;
                flpPenlist.Left = 0;
                flpPenlist.Top = 34;

                //labBJ.Text = Program.MTInfo.MicroTestRoomInfo;
                labBJ.Text = Program.CurrentClassInfo.ClassRoomInfo;
                if (string.IsNullOrEmpty(labBJ.Text))
                    labBJ.Text = Program.StudentInfo.Class;
                
                labBJ.Top = pnlTop.Bottom - labBJ.Height - 10;
                labBJ.Left = 20;
            }
            this.tlpBase.Visible = true;
        }

        /// <summary>
        /// load
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMain_Load(object sender, EventArgs e)
        {
            return;
        }

        /// <summary>
        /// 写入签到信息
        /// </summary>
        private void WriteStudentSignInData()
        {
            foreach (var item in Program.StudentInfo.BandList)
            {
                saveStrokeAsync.PutPenDownEvent(item.PenSerial);
                saveStrokeAsync.PutCoordinates(item.PenSerial, item.PageId, item.LeftBound + 100, item.TopBound + 100);
                saveStrokeAsync.PutPenUpEvent(item.PenSerial);
            }
        }


        /// <summary>
        /// 最小化窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnMin_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;

            //if (frmWait != null && !frmWait.IsDisposed)
            //    frmWait.WindowState = FormWindowState.Minimized;
        }
        /// <summary>
        /// 屏蔽回车空格
        /// </summary>
        /// <param name="keyData"></param>
        /// <returns></returns>
        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Enter || keyData == Keys.Space)
                return false;
            return base.ProcessDialogKey(keyData);
        }
        /// <summary>
        /// 关闭
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClose_Click(object sender, EventArgs e)
        {
            ELogger.Trace("用户点击了关闭课堂按钮！");
            if (DialogResult.OK == MessageBox.Show("是否退出？", "维思课堂", MessageBoxButtons.OKCancel, MessageBoxIcon.Question))
            {
                this.Close();
                Application.Exit();
            }
        }
        private FrmWait frmWait;
        /// <summary>
        /// 导出书写
        /// </summary>
        /// <param name="sener"></param>
        /// <param name="e"></param>
        private void btnExport_Click(object sener,EventArgs e)
        {
            //IsExporting = true;
            //frmWait = new FrmWait(OperationMode.ExportWriting, this);

            //frmWait.Show();
            //frmWait.TopMost = true;
            if (statusWindows.Count == 0||IsExporting)
                return;
            FolderBrowserDialog path = new FolderBrowserDialog();
            DialogResult dr= path.ShowDialog();
            if(dr==DialogResult.OK)
            {
                string savePath = path.SelectedPath;
                BackgroundWorkPara para = new BackgroundWorkPara();
                para.OperationMode = OperationMode.ExportWriting;
                para.Path = savePath;
                IsExporting = true;
                StudentToExportCount = statusWindows.Count;
                StudentExportedCount = 0;
                backgroundWorker.RunWorkerAsync(para);
                //FrmWait frm = new FrmWait(OperationMode.ExportWriting, this);
                //frm.ShowDialog();
                //if (ExportSuccess)
                //{
                //    ELogger.Trace(string.Format("保存{0} {1}", ExportSuccess ? "成功" : "失败",para.Path));
                //    MessageBox.Show("保存成功", "维思课堂", MessageBoxButtons.OK, MessageBoxIcon.Information);
                //}
                //else
                //{
                //    ELogger.Trace(string.Format("保存{0} {1}", ExportSuccess ? "成功" : "失败", para.Path));
                //    MessageBox.Show("保存失败", "维思课堂", MessageBoxButtons.OK, MessageBoxIcon.Information);
                //}
                frmWait = new FrmWait(OperationMode.ExportWriting, this);
                frmWait.TopMost = true;
                frmWait.Show();
                EnableButtons(false);
            }


        }
        private void EnableButtons(bool enable)
        {
            btnSave.Enabled = enable;
            btnZoomIn.Enabled = enable;
            btnZoomOut.Enabled = enable;
            btnChooseSym.Enabled = enable;
            btnBackground.Enabled = enable;
            btnGoToExam.Enabled = enable;
        }
        public void ShowExportResult()
        {
            EnableButtons(true);
            
            if (ExportSuccess)
            {
                ELogger.Trace(string.Format("保存{0} ", ExportSuccess ? "成功" : "失败"));
                MessageBox.Show("保存成功", "维思课堂", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                ELogger.Trace(string.Format("保存{0}", ExportSuccess ? "成功" : "失败"));
                MessageBox.Show("保存失败", "维思课堂", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        /// <summary>
        /// 设置button为disabled状态  在触发事件的按钮中disable自己会有问题
        /// </summary>
        /// <param name="btn"></param>
        private void DisableButton(object btn)
        {
            if(this.InvokeRequired)
            {
                Action<object> ac = new Action<object>(DisableButton);
                this.Invoke(ac, new object[] { btn });
            }
            else
            {
                (btn as ImageButton).NormalImage = Properties.Resources.btn_upload_disabled;
                (btn as ImageButton).Enabled = false;
            }
        }
       

        /// <summary>
        /// 放大界面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnZoomIn_Click(object sender, EventArgs e)
        {
            if (IsExporting)
                return;
            if (flpClient.Controls.Count == 0)
                return;
            int controlCount = flpClient.Controls.Count;
            for (int i = controlCount - 1; i > 0; i--)
            {
                flpClient.Controls.RemoveAt(i);
            }

            foreach (var item in statusWindows)
            {
                int width = item.Value.Width;
                int height = item.Value.Height;
                int index = -1;
                for (int i = 0; i < zoomValues.Count; i++)
                {
                    if(zoomValues[i].X==width&&zoomValues[i].Y==height)
                    {
                        index = i;
                        break;
                    }
                }
                if (index == zoomValues.Count - 1||index==-1)
                    break;
                index += 1;
                ZoomSize zs = zoomValues[index];
                
                width = zs.X;
                height = zs.Y;
                item.Value.SuspendLayout();
                item.Value.Width = width;
                item.Value.Height = height;
                int leftMargin = 0;
                if (index == 1)
                    leftMargin = (flpClient.Width - width) / 2-10;
                else if (index == 2)
                    leftMargin = 10;
                item.Value.Margin = new Padding(leftMargin, 10, leftMargin, 10);
                item.Value.ResumeLayout();
                windowWidth = width;
                windowHeight = height;
            }
        }
        /// <summary>
        /// 缩小界面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnZoomOut_Click(object sender, EventArgs e)
        {
            if (IsExporting)
                return;
            if (flpClient.Controls.Count == 0)
                return;
            int controlCount = flpClient.Controls.Count;

            int width = flpClient.Controls[0].Width;
            int height = flpClient.Controls[0].Height;
            int index = -1;
            for (int i = 0; i < zoomValues.Count; i++)
            {
                if (zoomValues[i].X == width && zoomValues[i].Y == height)
                {
                    index = i;
                    break;
                }
            }
            if (index == 0 || index == -1)
                return;
            index -= 1;
            flpClient.SuspendLayout();
            if (index == 0 && statusWindows.Count > 1)
                flpClient.Controls.Clear();


            foreach (var item in statusWindows)
            {
                ZoomSize zs = zoomValues[index];

                width = zs.X;
                height = zs.Y;
                item.Value.SuspendLayout();
                item.Value.Width = width;
                item.Value.Height = height;
                int leftMargin = 0;
                if (index == 0)
                    leftMargin = 20;
                else if (index == 1)
                    leftMargin = (flpClient.Width - width) / 2-10;
                else if (index == 2)
                    leftMargin = 10;
                item.Value.Margin = new Padding(leftMargin, 10, leftMargin, 10);
                item.Value.ResumeLayout();
                windowWidth = width;
                windowHeight = height;
                if (index == 0 && statusWindows.Count > 1)
                {
                    item.Value.SetLabelVisable(false);
                    //item.Value.Visible = false;
                    flpClient.Controls.Add(item.Value);

                }
            }
            flpClient.ResumeLayout();
            foreach (var item in flpClient.Controls)
            {
                (item as DrawingWindow).SetLabelVisable(true);
            }
        }
        /// <summary>
        /// 显示/隐藏背景
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnBackground_Click(object sender, EventArgs e)
        {
            if (IsExporting)
                return;
            if (statusWindows.Count == 0)
                return;
            ShowBackground = !ShowBackground;
            foreach (var item in statusWindows)
            {
                item.Value.SetBackgroundVisible(ShowBackground);
            }
            if (!ShowBackground)
            {
                btnBackground.NormalImage = Resources.oper_btn_showbg;
                btnBackground.HoverImage = Resources.oper_btn_showbg_hover;
                btnBackground.DownImage = Resources.oper_btn_showbg_active;
                btnBackground.DisableImage = Resources.oper_btn_showbg_disabled;
            }
            else
            {
                btnBackground.NormalImage = Resources.oper_btn_hidebg;
                btnBackground.HoverImage = Resources.oper_btn_hidebg_hover;
                btnBackground.DownImage = Resources.oper_btn_hidebg_active;
                btnBackground.DisableImage = Resources.oper_btn_hidebg_disabled;
            }
        }
        /// <summary>
        /// 考试名称tooltip
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void labKS_MouseEnter(object sender, EventArgs e)
        {
            toolTipExam.IsBalloon = false;
            toolTipExam.SetToolTip(this.labKS, labKS.Text);
        }
        
        /// <summary>
        /// 选择sym
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnChooseSym_Click(object sender, EventArgs e)
        {
            if (IsExporting)
                return;
            if(DialogResult.OK!= openFileDialog.ShowDialog())
            {
                return;
            }
            ELogger.Trace(string.Format("开始加载SYM文件{0}", openFileDialog.FileName));
            IsLoadingSym = true;
            if (backgroundWorker.IsBusy == true)
                return;
            BackgroundWorkPara para = new BackgroundWorkPara();
            para.OperationMode = OperationMode.LoadSym;
            para.Path = openFileDialog.FileName;
            backgroundWorker.RunWorkerAsync(para);

            FrmWait frmWait = new FrmWait(OperationMode.LoadSym, this);
            frmWait.ShowDialog();

            IsSymLoaded = true;
            Program.CurrentClassInfo.ClassSymTitle = openFileDialog.SafeFileName.Substring(0,openFileDialog.SafeFileName.Length-4);
            labKS.Text = "【" + Program.CurrentClassInfo.ClassSymTitle + "】";
            labKS.Top = labBJ.Top;
            labKS.Left = labBJ.Right;

            statusWindows.Clear();
            flpClient.Controls.Clear();

            windowWidth = 0;
            windowHeight = 0;
            LoadDrawingWindws();
            ELogger.Trace(string.Format("加载SYM文件{0}成功", Program.CurrentClassInfo.ClassSymTitle));

        }

        private void FrmClass_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Maximized&&frmWait!=null&&frmWait.IsDisposed==false)
            {
                frmWait.WindowState = FormWindowState.Normal;
                //frmWait.Show();
                frmWait.TopMost = true;
            }
            if (this.WindowState == FormWindowState.Minimized && frmWait != null && frmWait.IsDisposed == false)//捕获还原（Normal)事件  
            {
                //frmWait.Hide();
                frmWait.WindowState = FormWindowState.Minimized;

                frmWait.WindowState = FormWindowState.Minimized;

            }
        }

        /// <summary>
        /// 切换成考试模式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnGoToExam_Click(object sender, EventArgs e)
        {
            if (IsExporting)
                return;
            if (Program.CurrentClassInfo.Login==false)
            {
                MessageBox.Show("用户未登录，无法切换到考试模式！", "维思课堂", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if(DialogResult.OK==MessageBox.Show("是否切换到考试模式？", "维思课堂", MessageBoxButtons.OKCancel,MessageBoxIcon.Question))
            {
                ELogger.Trace("用户切换到考试模式");
                statusWindows.Clear();
                flpClient.Controls.Clear();
                Program.CurrentClassInfo.ClearSymPageImage();
                penItemList.Clear();
                flpPenlist.Controls.Clear();
                GC.Collect();
                this.Hide();
                FrmSwhich.SwhichFrm.SwichToScene(SceneType.Scene_Exam);
            }
        }
        public void SaveCurrentDrawingImageWhenExcpetion()
        {
            foreach (var item in statusWindows)
            {
                string key = item.Key;
                DrawingWindow dw = item.Value;
                dw.SaveDrawingImage();
            }
        }
    }

    class BackgroundWorkPara
    {
        public OperationMode OperationMode;
        public string Path = string.Empty;
    }

    

}
